#pragma once

#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
#include <fstream>
#include <assert.h>

#include "../Comm/Tool.hpp"
#include "../Comm/Log.hpp"

namespace Model_NS
{
    using namespace Tool_NS;
    using namespace Log_NS;

    const std::string question_list_path = "./Questions/Questions.list";
    const std::string question_path = "./Questions/";

    class Question
    {
    public:
        std::string _number;     // 题号
        std::string _title;      // 标题
        std::string _difficulty; // 难度
        int _cpu_limit;          // 时间限制 s
        int _mem_limit;          // 空间限制 KB
        std::string _desc;       // 题目描述
        std::string _default;    // 为用户提供的预设代码
        std::string _test;       // 题目的测试代码
    };

    class Model
    {
    public:
        Model() 
        {
            assert(LoadQuestionList(question_list_path));
        }
        ~Model() {}
    public:
        // 加载题目列表
        bool LoadQuestionList(const std::string &question_list)
        {
            std::ifstream in(question_list);
            if (!in.is_open())
            {
                std::cout << question_list << std::endl;
                LOG(Fatal) << "加载题库失败,请检查题库是否存在" << std::endl;
                return false;
            }

            std::string line;
            while (std::getline(in, line))
            {
                std::vector<std::string> v_sub;
                StringTool::SplitString(line, &v_sub, " ");

                if (v_sub.size() != 5)
                {
                    LOG(Warning) << "加载某个题目失败,请检查格式是否正确" << std::endl;
                    continue;
                }

                Question q;
                q._number = v_sub[0];
                q._title = v_sub[1];
                q._difficulty = v_sub[2];
                q._cpu_limit = std::stoi(v_sub[3]);
                q._mem_limit = std::stoi(v_sub[4]);

                std::string path = question_path + q._number + "/";

                FileTool::ReadFile(path + "Desc.txt", &q._desc, true);
                FileTool::ReadFile(path + "Default_Code.cpp", &q._default, true);
                FileTool::ReadFile(path + "Test_Code.cpp", &q._test, true);

                _questions.insert(std::make_pair(q._number,q));
            }
            LOG(Info) << "加载题库完毕" << std::endl;
            in.close();

            return true;
        }

        // 获取所有题目
        bool GetAllQuestions(std::vector<Question> *out)
        {
            if (_questions.empty())
            {
                LOG(Warning) << "获取所有题目失败" << std::endl;
                return false;
            }

            for (const auto &q : _questions)
            {
                out->push_back(q.second);
            }

            return true;
        }

        // 获取特定题目
        bool GetOneQuestion(const std::string &number, Question *q)
        {
            const auto &iter = _questions.find(number);
            if (iter == _questions.end())
            {
                LOG(Warning) << "获取题目" << number << "失败" << std::endl;

                return false;
            }

            *q = iter->second;
            return true;
        }

    private:
        std::unordered_map<std::string, Question> _questions;
    };
}